package moonlit.chill.pay.service.impl.async;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import moonlit.chill.pay.asyncFactory.AsyncFactory;
import moonlit.chill.pay.asyncFactory.AsyncFactoryManager;
import moonlit.chill.pay.cache.PayConfigDataCache;
import moonlit.chill.pay.cache.PayMappingsDataCache;
import moonlit.chill.pay.cache.WaitingPayCache;
import moonlit.chill.pay.constants.PayStrategySuffix;
import moonlit.chill.pay.factory.PayFactory;
import moonlit.chill.pay.service.AsyncForPayBusinessHandler;
import moonlit.chill.pay.service.AsyncServiceForPay;
import moonlit.chill.pay.service.PayStrategy;
import moonlit.chill.pay.vo.PayResult;
import moonlit.chill.pay.vo.PaySearchParam;
import moonlit.chill.pay.vo.PaySearchRule;
import moonlit.chill.pay.vo.TradeParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/**
 * @author MoonlitChill
 * @date 2024/4/24 15:22
 */
@Slf4j
@Service
public class AsyncServiceForPayImpl implements AsyncServiceForPay {

    @Autowired
    private AsyncForPayBusinessHandler businessHandler;

    @Autowired
    private PayFactory payFactory;

    @Autowired
    private WaitingPayCache waitingPayCache;

    @Autowired
    private PayMappingsDataCache payMappingsDataCache;

    @Autowired
    private PayConfigDataCache payConfigDataCache;

    @Override
    @Async("asyncServiceExecutor")
    public void executeAsync(TradeParam tradeParam) {
        log.info("当前线程{}查询待支付订单 获取参数{}", Thread.currentThread().getName(), JSONUtil.toJsonStr(tradeParam));
        PaySearchParam search = tradeParam.getSearchParam();
        String code = null;
        try {
            boolean flag = businessHandler.businessHandler(tradeParam);
            if (flag) {
                //TODO 根据业务需求获取code
                code = payMappingsDataCache.getCode(null, tradeParam.getPayType(), tradeParam.getPayChannel());
                if (StrUtil.isEmpty(code)) {
                    waitingPayCache.offer(tradeParam, System.currentTimeMillis() + search.getPaySearchRule().getIntervalTime() * 1000L);
                    log.info("当前线程{}获取CODE为null", Thread.currentThread().getName());
                    return;
                }
                payConfigDataCache.setCode(code);
                PayStrategy payStrategy = payFactory.getPayStrategy(tradeParam.getPayType() + PayStrategySuffix.QUERY);
                if (payStrategy != null) {
                    PayResult<?> queryResult = payStrategy.payForPayQuery(tradeParam);
                    if (queryResult.isSuccess()) {
                        AsyncFactoryManager.me().execute(AsyncFactory.payQuerySuccess(queryResult, tradeParam));
                    } else {
                        offer(tradeParam, search);
                    }
                }
            }
        } catch (Exception e) {
            log.error("当前线程{}发起查询产生异常：{}", Thread.currentThread().getName(), e.getMessage(), e);
            offer(tradeParam, search);
        } finally {
            if (StrUtil.isNotEmpty(code)) {
                payConfigDataCache.remove();
            }
        }
    }

    private void offer(TradeParam tradeParam, PaySearchParam search) {
        PaySearchRule rule = search.getPaySearchRule();
        int level = rule.getLevel();
        int count = rule.getCount();
        //判断等级 如果不处于最高等级 提升等级 否则放弃该通知
        if (PaySearchRule.LEVEL_9.getLevel() > level) {
            //判断次数 如果searchCount + 1 < count 代表还处于当前等级 否则需要次数归0 提升等级
            if (search.getSearchCount() + 1 < count) {
                search.setSearchCount(search.getSearchCount() + 1);
            } else {
                search.setSearchCount(0);
                level += 1;
                search.setPaySearchRule(PaySearchRule.getCallBackTypeByLevel(level));
            }
            tradeParam.setSearchParam(search);
            waitingPayCache.offer(tradeParam, System.currentTimeMillis() + search.getPaySearchRule().getIntervalTime() * 1000L);
        }
    }
}
